/*
 * vmtime.c
 */

#include <stdio.h>
#include <time.h>

#ifdef _MSDOS
#include <dos.h>
#elif defined(_WIN32)
#include <windows.h>
#else
#error DOS or WIN32 required
#endif

#include "vmbdoor.h"

#ifdef _MSDOS
void ChangeSystemClock(struct tm *t)
{
	struct _dosdate_t dos_day;
	struct _dostime_t dos_tm; 

	dos_day.year 	= t->tm_year + 1900;
	dos_day.month	= t->tm_mon + 1;
	dos_day.day		= t->tm_mday;
	_dos_setdate(&dos_day);

	dos_tm.hour 	= t->tm_hour;
	dos_tm.minute 	= t->tm_min;
	dos_tm.second	= t->tm_sec;
	dos_tm.hsecond	= 0;
	_dos_settime(&dos_tm);
}
#elif defined (_WIN32)
void ChangeSystemClock(struct tm *t)
{
	SYSTEMTIME sys;
	
	sys.wYear 	= t->tm_year + 1900;
	sys.wMonth 	= t->tm_mon + 1;
	sys.wDay	= t->tm_mday;
	sys.wHour	= t->tm_hour;
	sys.wMinute	= t->tm_min;
	sys.wSecond	= t->tm_sec;
	sys.wMilliseconds = 0;
	
	SetSystemTime(&sys);
}
#endif

struct tm *divtime(time_t timeval)
{
	static const unsigned long day_per_month[][12] = {
		{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
		{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
	};
	static struct tm t;
	
	for (t.tm_year = 1970; t.tm_year < 2039; t.tm_year++) {
		unsigned long sec_per_year;
		
		if (t.tm_year & 3) {	/*not leap year */
			sec_per_year = 365L * 24L * 60L * 60L;
		}
		else {
			sec_per_year = 366L * 24L * 60L * 60L;
		}
		
		if (timeval >= sec_per_year) {
			timeval -= sec_per_year;
		}
		else {
			break;
		}
	}
	t.tm_year -= 1900;
	
	for (t.tm_mon = 0; t.tm_mon < 12; t.tm_mon++) {
		unsigned long sec_per_month;
		
		if (t.tm_year & 3) {
			sec_per_month = day_per_month[0][t.tm_mon] * 24L * 60L * 60L;
		}
		else {
			sec_per_month = day_per_month[1][t.tm_mon] * 24L * 60L * 60L;
		}
		
		if (timeval >= sec_per_month) {
			timeval -= sec_per_month;
		}
		else {
			break;
		}
	}
	
	for (t.tm_mday = 1; t.tm_mday <= 31; t.tm_mday++) {
		if (timeval >= 24L * 60L * 60L) {
			timeval -= 24L * 60L * 60L;
		}
		else {
			break;
		}
	}
	
	for (t.tm_hour = 0; t.tm_hour < 24; t.tm_hour++) {
		if (timeval >= 60L * 60L) {
			timeval -= 60L * 60L;
		}
		else {
			break;
		}
	}
	
	for (t.tm_min = 0; t.tm_min < 60; t.tm_min++) {
		if (timeval >= 60) {
			timeval -= 60;
		}
		else {
			break;
		}
	}

	t.tm_sec = timeval;
	
	return &t;
}
/*
 * main
 */
int main ()
{
	time_t host_time;
	signed long offset;
	uint32 command;
	
	/* are we running in VMware ? 	*/
	if (VMGetVersion() == 0) {
		printf("Not running inside VMware.\n");
		return 0;
	}

	command = VMCMD_GET_TIME;
	VMBackDoor((uint32 *)&host_time, NULL, &command, (uint32 *)&offset);
	
	if (host_time) {
		/* convert to localtime */
		host_time -= (offset * 60);
		
		ChangeSystemClock(divtime(host_time));
		printf("%s\n", asctime(divtime(host_time)));
	}

	return 1;
}
/* End of File */
